#pragma once

#include <gl\glew.h>
#include <map>
#include <vector>
#include <set>

#include "gamestate.h"
#include "pickable.h"

class Model;

enum EntityType{ET_INVALID = 1,
                ET_TILE = 2,
                ET_IMPROVEMENT = 4,
                ET_ARMY = 8,
                ET_UNIT = 16,
                ET_CITY  = 32};

class Entity:public Pickable{
    public:
        Entity();
        virtual void Update(int dt){dt = dt;}
        virtual void EndTurn();
        virtual void Order(int target){ target = target; }
        virtual EntityType GetType(){ return ET_INVALID; }

        virtual void Select(){ selected = true; }
        virtual void Deselect(){ selected = false; }
        bool IsSelected(){ return selected; }
        int GetOwner(){ return owner; }
        std::string GetName(){ return name; }

        void SetIndex(int ind){ index = ind; }
        int GetIndex(){ return index; }
        int Getx(){ return gamestate->xComponent(index); }
        int Gety(){ return gamestate->yComponent(index); }

        void SetName(std::string n){ name = n; }
        void SetOwner(int o){ owner = o; }

        GLuint GetBuildPic(){ return buildPic; }
        void SetBuildPic(GLuint bp){ buildPic = bp; }

        virtual std::set<int> GetBuildingIDs(){ return std::set<int>(); }
        virtual std::set<int> GetConstructionQueueIDs(){ return std::set<int>(); }

		void AddToUnits(std::set<int> unitIDsToAdd);
		void AddToUnits(int unit);
		void SetCanContainUnits(bool can){ canContainUnits=can; }
        virtual bool CanContainUnits(){ return canContainUnits; }
        std::set<int> GetUnitIDs(){ return unitIDs; }
        bool HasCombatUnits();
        void RemoveFromUnits(int unit);
        void RemoveFromUnits(std::set<int> unitIDsToRemove);
        void RemoveAllUnits(){ unitIDs.clear(); }

        void SetConstructionOptionNames( std::set<std::string> names ){ constructionOptionNames = names; }
        void SetRecruitmentOptionNames( std::set<std::string> names ){ recruitmentOptionNames = names; }
        virtual void AddConstructionOption(std::string str){ constructionOptionNames.insert(str); }
        virtual void RemoveConstructionOption(std::string str){ constructionOptionNames.erase(str); }
        virtual void AddRecruitmentOption(std::string str){ recruitmentOptionNames.insert(str); }
        virtual std::set<std::string> GetConstructionOptionNames(){ return constructionOptionNames; }
        virtual std::set<std::string> GetImprovementOptionNames(){ return std::set<std::string>(); }
        virtual std::set<std::string> GetRecruitmentOptionNames(){ return recruitmentOptionNames; }

        void AddUnitToRecruitmentQueue(int id){ recruitmentQueue.push_front(id); }

        virtual void SetCityOwner(int id){ city_owner = id; }
        virtual int GetCityOwner(){ return city_owner; }

        void SetContainingEntity(int ent){ containingEntity = ent; }
        int ContainingEntity(){ return containingEntity; }

        void SetModelName(std::string str){ model_name = str; }
        virtual std::string GetModelName(){ return model_name; }

        void SetTurnsToComplete(int turns){ turns_to_complete = turns; }
        virtual int GetTurnsToComplete(){ return turns_to_complete; }
        void DecrementTurnsToComplete(){ --turns_to_complete; }

        virtual bool IsConstructionPaused(){ return construction_paused; }
        virtual void SetConstructionPaused(bool pause){ construction_paused = pause; }

        void SetValidPosition(bool valid){ valid_position = valid; }
        bool IsInAValidPosition(){ return valid_position; }

    protected:
        int city_owner;
        int owner;

        int turns_to_complete;
        int index;

        bool selected;
        bool valid_position;
        bool canContainUnits;

        std::string name;
        std::string script;
        std::string scriptLocation;

        GLuint buildPic;

        std::string model_name;

        std::map<std::string,int> luaIntVars;

        std::set<int> unitIDs;

        std::deque<int> recruitmentQueue;

        std::set<std::string> constructionOptionNames;
        std::set<std::string> recruitmentOptionNames;

        bool construction_paused;

        int containingEntity;

        // Stock lua callouts
        int refInit;
        int refEndTurn;
        int refCalculateCoin;
};
